package at.fhj.itm10.ticketmaster.beans;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.annotation.ManagedBean;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

import org.primefaces.model.UploadedFile;

import at.fhj.itm10.ticketmaster.dao.AddressDAO;
import at.fhj.itm10.ticketmaster.dao.DAOException;
import at.fhj.itm10.ticketmaster.dao.EventDAO;
import at.fhj.itm10.ticketmaster.dao.EventTypeDAO;
import at.fhj.itm10.ticketmaster.dao.impl.DAOFactoryImpl;
import at.fhj.itm10.ticketmaster.models.Address;
import at.fhj.itm10.ticketmaster.models.Customer;
import at.fhj.itm10.ticketmaster.models.Event;
import at.fhj.itm10.ticketmaster.models.EventType;

public class EventBean {
	private EventDAO dao;
	private EventTypeDAO eventtypeDao;
	private List<EventType> eventtypes;
	private Event event;
	private Date start;
	private Date end;
	private EventType category;
	private List<Event> eventsList = new ArrayList<Event>();
	private List<Event> eventsl = new ArrayList<Event>();

	/* Generate Adress-List */
	// Adress variablen
	private List<Address> adresslist = new ArrayList<Address>();
	private AddressDAO addressDao;
	private Address address;
	private Address conv;
	private String name;
	private String street;
	private String zip;
	private String country;
	private String city;

	// Event variablen
	private String eventName;
	private String date;
	private String enter;
	private String begin;
	private String description;
	private int eventType;
	private double ticketPrice; // singlePrice??
	private int ticketAmount;
	private UploadedFile flyer;
	private Long eventId;

	// normal search
	private String namesearch;

	// extended search
	private String eventcount;

	/*
	 * List for putting events into HashMap HashMap for getting data into
	 * warenkorb.xhtml Authors: Martin Kropf, Wolfgang Schrattner, Reinhard
	 * Rebernig, Benjamin Hirt
	 */
	private HashMap<String, Event> events = new HashMap<String, Event>();
	private double singlePrice;

	public EventBean() {
		super();
		init();
	}

	// Reini braucht Preis, Title, Datum, Foto, ---> HashMap
	@PostConstruct
	public void init() {
		try {
			// getDAO
			DAOFactoryImpl daoFactoryImpl;
			daoFactoryImpl = new DAOFactoryImpl();
			setDao(daoFactoryImpl.getEventDAO());
			setAdao(daoFactoryImpl.getAddressDAO());
			setEventtypeDao(daoFactoryImpl.getEventTypeDAO());

			initEvents();
			eventsList = dao.findAll();
			adresslist = addressDao.findAll();
			eventcount = "Bisher noch keine Suchergebnisse";
			// insert test data
			// dao.insert(new
			// Event(1,"TestEvent1","2012-11-12 12:00:00",1,1,1,100.00,999,1,0));
			// dao.insert(new
			// Event(2,"TestEvent2","2012-11-13 12:00:00",1,1,1,50.00,888,1,0));

			// get test data
			// setEvent(dao.findById(1));

			// print test data to console
			// System.err.println(getEvent().toString());
			selectEventType();
		} catch (DAOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		// setEvent(new
		// Event(1,"TestEvent1","2012-11-12 12:00:00",1,1,1,100.00,999,1,0));
		
	}
	
	public String initForAdd() {
		
		FacesContext context = FacesContext.getCurrentInstance();
		int customerId = (Integer) context.getApplication().evaluateExpressionGet(context, "#{loginBean.getCustomer().getId()}", Integer.class);
		
		if (customerId == 0) {
	        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
	        try {
				ec.redirect(ec.getRequestContextPath() + "/login.xhtml");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        
	        return null;
	        
	    }
		
		return null;
		
	}

	public String initForEdit() {

		try {
			event = dao.findById(getEventId());
		} catch (DAOException e) {
			e.printStackTrace();
		}
		
		if (event == null) {
			ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
			try {
				ec.redirect(ec.getRequestContextPath() + "/noevent.xhtml");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		FacesContext context = FacesContext.getCurrentInstance();
		int customerId = (Integer) context.getApplication().evaluateExpressionGet(context, "#{loginBean.getCustomer().getId()}", Integer.class);
		
		if (customerId == 0) {
	        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
	        try {
				ec.redirect(ec.getRequestContextPath() + "/login.xhtml");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        
	        return null;
	    }
		else if(event.getFkCustomerId() != customerId) {
			ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
	        try {
				ec.redirect(ec.getRequestContextPath() + "/nopermission.xhtml");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        
	        return null;
		}

		try {
			address = addressDao.findById(this.event.getFkAddressId());
		} catch (DAOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		this.eventName = event.getName();
		// TODO: Add missing properties
		
		return null;

	}

	/*
	 * writes data into HashMap
	 */
	public void initEvents() {

		Event e;

		for (int i = 0; i < eventsList.size(); i++) {
			e = eventsList.get(i);

			events.put((Long.toString(e.getId())), e);
		}

	}

	/*
	 * grab events for warenkorb.xhtml
	 */
	public Event showEventInfos(String id) {
		Event eventData = null;

		if (events.containsKey(id)) {
			eventData = events.get(id);

		} else {
			System.err.println("ERROR: No Event with this id -> " + id + "!");
		}

		return eventData;
	}

	/*
	 * get price for a single Event
	 */
	public double getTicketPrice(String id) {

		singlePrice = events.get(id).getTicketPrice();
		return singlePrice;

	}

	public void selectEventType() {

		try {
			setEventtypes(eventtypeDao.findAll());
		} catch (DAOException e) {
			e.printStackTrace();
		}
	}

	public String writeFlyerToFileSystem() {

		if (flyer != null) {

			File f = new File("path/to/" + flyer.getFileName()); // TODO:
																	// richtigen
																	// Pfad
																	// eintragen

			try {

				InputStream fileInputStream = flyer.getInputstream();

				OutputStream fileOutputStream = new FileOutputStream(f);

				byte buf[] = new byte[1024];
				int len;

				while ((len = fileInputStream.read(buf)) > 0) {
					fileOutputStream.write(buf, 0, len);
				}

				fileOutputStream.close();
				fileInputStream.close();

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			return f.getAbsolutePath();
		}
		return "";
	}

	public void setFlyerPath(String path) {
		event.setFlyer(path);
	}

	public String saveNewEvent() throws ParseException {		
		System.out.println("Dominik: saveNewEvent");
		// Todo: Eventuell Felder validieren
		Address address = new Address();
		address.setCity(this.getCity());
		address.setCountry(this.getCountry());
		address.setStreet(this.getStreet());
		address.setZip(this.getZip());
		address.setName(this.getName());
		// F
		System.out.println("Dominik: zuweisen: " + this.getEventName());

		try {
			addressDao.insert(address);
			System.out.println("Dominik: wir sind im try-block");
		} catch (DAOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("Dominik: wir sind im catch-block");
		}
		System.out.println("Dominik: nach insert adress");

		event = new Event();
		event.setFkAddressId(address.getId());

		// Select event type
		event.setFkEventtypeId(eventType);
		// selectEventType();

		// Write flyer to file system and set path

		this.setFlyerPath(this.writeFlyerToFileSystem());

		// Todo: get UserId from Session????
		// event.setFkCustomerId(fkCustomerId);

		// System.out.println("Dominik: vor setFkCustomerId" + customerId);
		FacesContext context = FacesContext.getCurrentInstance();
		int customerId = (Integer) context.getApplication()
				.evaluateExpressionGet(context,
						"#{loginBean.getCustomer().getId()}", Integer.class);
		event.setFkCustomerId((int) customerId);

		System.out.println("Dominik: Customer = " +  context.getApplication()
		.evaluateExpressionGet(context,
				"#{loginBean.getCustomer()}", Customer.class));
		
		System.out.println("Dominik: CustomerID" + customerId);

		event.setName(this.getEventName());
		// Todo: beginn - was ist das richitge Beginn?
		// Todo: einlass = enter?

		// Date Formatter für das Datum in Datetime
		DateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");
		DateFormat dateFormatter1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date dateRes = dateFormatter.parse(date);
		// dateFormatter1.format(dateRes);

		// Date Formatter für Eintritt in timestamp
		DateFormat enterBeginFormatter = new SimpleDateFormat("HH:mm");
		DateFormat enterBeginFormatter1 = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss");
		Date eintritt = enterBeginFormatter.parse(enter);
		enterBeginFormatter1.format(eintritt);

		// Date Formatter für Begin in timestamp
		Date beginn = enterBeginFormatter.parse(begin);
		enterBeginFormatter1.format(beginn);

		// @Benjamin - temporär da datepicker bei mir nicht funktioniert hat
		if (date == null) {
			event.setDateTime(dateFormatter.format(new Date()));
		} else {
			event.setDateTime(dateFormatter1.format(dateRes));
		}
		System.out.println("Dominik: eventBean" + event.getDateTime());

		event.setEnter(enterBeginFormatter1.format(eintritt));
		event.setBegin(enterBeginFormatter1.format(beginn));
		event.setDescription(this.getDescription());
		event.setTicketPrice(this.getTicketPrice());
		event.setTicketAmount(this.getTicketAmount());

		System.out.println("Dominik: vor Insert Event" + event.getFkAddressId()
				+ ":" + event.getFkCustomerId() + ":"
				+ event.getFkEventtypeId());

		try {
			dao.insert(event);
		} catch (DAOException e1) {
			e1.printStackTrace();
			return "Speichernfehlgeschlagen";
		}
		System.out.println("Dominik: nach Insert Event");
		return "SpeichernErfolgreich";

	}

	public String getEventName() {
		return eventName;
	}

	public void setEventName(String eventName) {
		System.out.println("Dominik: setEventName: " + eventName);
		this.eventName = eventName;
	}

	public int getEventType() {
		return eventType;
	}

	public void setEventType(int eventType) {
		this.eventType = eventType;
	}

	public String getDate() {
		return date;
	}

	public void setDate(String date) {
		this.date = date;
	}

	public String getEnter() {
		return enter;
	}

	public void setEnter(String enter) {
		this.enter = enter;
	}

	public String getBegin() {
		return begin;
	}

	public void setBegin(String begin) {
		this.begin = begin;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public double getTicketPrice() {
		return ticketPrice;
	}

	public void setTicketPrice(double ticketPrice) {
		this.ticketPrice = ticketPrice;
	}

	public int getTicketAmount() {
		return ticketAmount;
	}

	public void setTicketAmount(int ticketAmount) {
		this.ticketAmount = ticketAmount;
	}

	public UploadedFile getFlyer() {
		return flyer;
	}

	public void setFlyer(UploadedFile flyer) {
		this.flyer = flyer;
	}

	public Long getEventId() {
		return eventId;
	}

	public void setEventId(Long eventId) {
		this.eventId = eventId;
	}

	public String editEvent() throws ParseException {

		address.setCity(this.getCity());
		address.setCountry(this.getCountry());
		address.setStreet(this.getStreet());
		address.setZip(this.getZip());
		address.setName(this.getName());
		address.setId(event.getFkAddressId());

		try {
			addressDao.update(address);
		} catch (DAOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		event.setFkAddressId(address.getId());

		// Select event type
		event.setFkEventtypeId(eventType);
		// selectEventType();

		// Write flyer to file system and set path

		this.setFlyerPath(this.writeFlyerToFileSystem());

		// Todo: get UserId from Session????
		// event.setFkCustomerId(fkCustomerId);

		FacesContext context = FacesContext.getCurrentInstance();

		int customerId = (Integer) context.getApplication()
				.evaluateExpressionGet(context,
						"#{loginBean.getCustomer().getId()}", Integer.class);
		event.setFkCustomerId((int) customerId);
		System.out.println("Dominik: CustomerID 2222222" + customerId);
		
		//Syso Wolfgang
		System.out.println("Dominik: Customer = " +  context.getApplication()
		.evaluateExpressionGet(context,
				"#{loginBean.getCustomer()}", Customer.class));

		event.setName(this.getEventName());
		// Todo: beginn - was ist das richitge Beginn?
		// Todo: einlass = enter?

		// Date Formatter für das Datum in Datetime
		/*
		 * DateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");
		 * DateFormat dateFormatter1 = new
		 * SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date =
		 * dateFormatter.parse(date); dateFormatter1.format(date);
		 */

		// Date Formatter für Eintritt in timestamp
		DateFormat enterBeginFormatter = new SimpleDateFormat("HH:mm");
		DateFormat enterBeginFormatter1 = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss");
		DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd");
		Date eintritt = enterBeginFormatter.parse(enter);
		enterBeginFormatter1.format(eintritt);

		// Date Formatter für Begin in timestamp
		Date beginn = enterBeginFormatter.parse(begin);
		enterBeginFormatter1.format(beginn);

		// @Benjamin - temporär da datepicker bei mir nicht funktioniert hat
		if (date == null) {
			event.setDateTime(dateFormatter.format(new Date()));
		} else {
			event.setDateTime(dateFormatter.format(date));
		}

		event.setEnter(enterBeginFormatter1.format(eintritt));
		event.setBegin(enterBeginFormatter1.format(beginn));
		event.setDescription(this.getDescription());
		event.setTicketPrice(this.getTicketPrice());
		event.setTicketAmount(this.getTicketAmount());
		event.setId(this.eventId);

		try {
			dao.update(event);
		} catch (DAOException e1) {
			// TODO Auto-generated catch block
			return "Speichern fehlgeschlagen " + e1.getMessage();
		}

		return "Speichern erfolgreich";

	}

	public EventDAO getDao() {
		return dao;
	}

	public void setDao(EventDAO dao) {
		this.dao = dao;
	}

	public Event getEvent() {
		return event;
	}

	public void setEvent(Event event) {
		this.event = event;
	}

	public Date getStart() {
		return start;
	}

	public void setStart(Date start) {
		this.start = start;
	}

	public Date getEnd() {
		return end;
	}

	public void setEnd(Date end) {
		this.end = end;
	}

	public EventType getCategory() {
		return category;
	}

	public void setCategory(EventType category) {
		this.category = category;
	}

	public List<Event> getEventsl() {
		return eventsl;
	}

	public void setEventsl(List<Event> eventsl) {
		this.eventsl = eventsl;
	}

	/*
	 * Extended Search Author: Gerald Hambrosch
	 */

	// Method to call EventDAO and perform extended Search
	public void doExtendedSearch() throws DAOException, SQLException {
		// clear last search
		resetSearch();
		// System.out.println(address.getName());
		if (address != null) {
			List<Event> atmp = dao.findByAddress(address.getId());
			for (Event e : atmp) {
				this.eventsl.add(e);

			}

			for (Event el : eventsl) {
				System.out.println(el.getName());
			}

		}

		if (category != null) {
			// create temp-list and write each element of this list into the
			// eventsl-list
			List<Event> ctmp = dao.findByCategory(category.getId());

			for (Event e : ctmp) {
				eventsl.add(e);
			}

			for (Event k : eventsl) {
				System.out.println(k.getName());
			}

		}
		// if only start-date is set - start becomes the exact date to find
		if (end == null) {
			end = start;
		}

		if ((start != null) && (end != null)) {

			// search for category
			SimpleDateFormat dFormat = new SimpleDateFormat(
					"yyyy-MM-dd hh:mm:ss");
			List<Event> dtmp = dao.findByDate(dFormat.format(start),
					dFormat.format(end));

			for (Event e : dtmp) {
				eventsl.add(e);
			}
		}

		if (eventsl.size() != 0) {
			eventcount = String.valueOf(eventsl.size())
					+ " Ergebnisse gefunden";
		}

	}

	// method to delete search results
	public void resetSearch() {
		if (!eventsl.isEmpty()) {
			eventsl.clear();

			start = null;
			end = null;
			address = null;
			category = null;
			eventcount = "Bisher noch keine Suchergebnisse";
		}

	}

	/*
	 * normal search Author: Christopher Barilich
	 */

	public void doNormalSearch() throws DAOException, SQLException {

		// clear last search
		resetSearch();

		if (namesearch != "") { // empty searchbox -> empty string

			// add events to eventslist
			List<Event> atmp = dao.findByName(getNamesearch());
			for (Event e : atmp) {
				this.eventsl.add(e);

			}

			// log found events
			for (Event el : eventsl) {
				System.out.println(el.getName());
			}

			if (eventsl.size() != 0) {
				eventcount = String.valueOf(eventsl.size())
						+ " Ergebnisse gefunden";
			}

		}

	}

	public List<Address> getAdresslist() {
		return adresslist;
	}

	public void setAdresslist(List<Address> adresslist) {
		this.adresslist = adresslist;
	}

	public AddressDAO getAdao() {
		return addressDao;
	}

	public void setAdao(AddressDAO adao) {
		this.addressDao = adao;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		this.street = street;
	}

	public String getZip() {
		return zip;
	}

	public void setZip(String zip) {
		this.zip = zip;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getNamesearch() {
		return namesearch;
	}

	public void setNamesearch(String namesearch) throws DAOException,
			SQLException {
		this.namesearch = namesearch;

		doNormalSearch();

	}

	public Address getConv() {
		return conv;
	}

	public void setConv(Address conv) {
		this.conv = conv;
	}

	public String getEventcount() {
		return eventcount;
	}

	public void setEventcount(String eventcount) {
		this.eventcount = eventcount;
	}

	// returns event infos and if the event id is not valid this function
	// returns a dummy event

	public Event showEventInfosWithDummy(String id) {
		Event eventData = null;

		if (events.containsKey(id)) {
			eventData = events.get(id);

		} else {
			System.err.println("ERROR: No Event with this id -> " + id + "!");
			eventData = new Event();
			eventData.setName("This event is not available");
			eventData.setTicketPrice(0);
		}

		return eventData;
	}

	public List<EventType> getEventtypes() {
		return eventtypes;
	}

	public void setEventtypes(List<EventType> eventtypes) {
		this.eventtypes = eventtypes;
	}

	public EventTypeDAO getEventtypeDao() {
		return eventtypeDao;
	}

	public void setEventtypeDao(EventTypeDAO eventtypeDao) {
		this.eventtypeDao = eventtypeDao;
	}

}
